package org.jeecg.modules.tt_question_collect.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import kong.unirest.HttpResponse;
import kong.unirest.JsonNode;
import kong.unirest.ObjectMapper;
import kong.unirest.Unirest;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.system.mapper.SysDictItemMapper;
import org.jeecg.modules.tt_question_collect.entity.TtPlanConfirm;
import org.jeecg.modules.tt_question_collect.entity.TtQuestionCollect;
import org.jeecg.modules.tt_question_collect.service.ITtPlanConfirmService;
import org.jeecg.modules.tt_question_collect.service.ITtQuestionCollectService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.xml.bind.DatatypeConverter;
import java.io.*;
import java.util.Arrays;
import java.util.List;

/**
 * @Description: JIRA API 接口
 * @ClassName JiraApiController
 * @Author WSC
 * @Date 2021/2/22 17:28
 * @Version 1.0
 */
@Api(tags = "JIRA API 接口")
@RestController
@RequestMapping("/request/jiraSync")
@Slf4j
public class JiraApiController extends JeecgController<TtQuestionCollect, ITtQuestionCollectService> {

    @Autowired
    private ITtQuestionCollectService ttQuestionCollectService;

    @Autowired
    private ITtPlanConfirmService ttPlanConfirmService;

    @Resource
    private SysDictItemMapper sysDictItemMapper;

    public static String CREATE_ISSUE_URL;

    public static String GET_ISSUE_URL;

    public static String ADD_ISSUE_ATTACHMENTS;

    public static String USERNAME;

    public static String PASSWORD;

    @Value("${jeecg.jira.issue.create}")
    public void setCreateIssueUrl(String createIssueURL) {
        CREATE_ISSUE_URL = createIssueURL;
    }

    @Value("${jeecg.jira.issue.get}")
    public void setGetIssueUrl(String getIssueURL) {
        GET_ISSUE_URL = getIssueURL;
    }

    @Value("${jeecg.jira.issueAttachments.add}")
    public void setAddIssueAttachments(String addIssueAttachments) {
        ADD_ISSUE_ATTACHMENTS = addIssueAttachments;
    }

    @Value("${jeecg.jira.username}")
    public void setUsername(String username) {
        USERNAME = username;
    }

    @Value("${jeecg.jira.password}")
    public void setPassword(String password) {
        PASSWORD = password;
    }

    @Value(value = "${jeecg.path.upload}")
    private String uploadPath;


    @ApiOperation(value = "JIRA-创建问题", notes = "JIRA-创建问题")
    @PostMapping(value = "/create/issue/{id}")
    public Result<JSONObject> createIssue(@PathVariable("id") String id) {
        Result<JSONObject> result = new Result<>();
        TtQuestionCollect questionCollect = ttQuestionCollectService.getById(id);
        if ("1".equals(questionCollect.getIsjira())) {
            result.setSuccess(false);
            result.setMessage("请勿重复同步！");
            return result;
        }
        TtPlanConfirm planConfirm = ttPlanConfirmService.getbyquestionid(id);
        Object requestBody = getRequestBody(questionCollect, planConfirm);
        HttpResponse<JsonNode> response = httpKitPostJson(requestBody);
       // log.info("同步JIRA需求问题-->" + id + "--->" + JSON.toJSONString(response));
        if (201 == response.getStatus()) {
            ttQuestionCollectService.setJiraIdOrKey(id, response.getBody());
            if (oConvertUtils.isNotEmpty(questionCollect.getFileguid())) {
                JSONObject jsonObject = JSONObject.parseObject(response.getBody().toString());
                String jiraId = jsonObject.getString("id");
                String jiraKey = jsonObject.getString("key");
                String[] files = questionCollect.getFileguid().split(",");
                for (int i = 0; i < files.length; i++) {
                    try {
                        CloseableHttpResponse responseFile = httpKitPostByFile(jiraKey, new File(uploadPath + "/" + files[i]));
                        log.info("同步JIRA添加附件-->" + jiraKey + "--->" + (uploadPath + "/" + files[i]) + "--->" + responseFile.getStatusLine());
                        log.info("同步JIRA添加附件-->" + jiraKey + "--->" + (uploadPath + "/" + files[i]) + "--->" + EntityUtils.toString(responseFile.getEntity()));
                    }
                    catch (FileNotFoundException e) {
                        e.printStackTrace();
                        log.info("同步JIRA添加附件-->" + jiraKey + "--->" + (uploadPath + "/" + files[i]), e);
                    }
                    catch (IOException e) {
                        e.printStackTrace();
                        log.info("同步JIRA添加附件-->" + jiraKey + "--->" + (uploadPath + "/" + files[i]), e);
                    }
                }
            }
            if (null != planConfirm && oConvertUtils.isNotEmpty(planConfirm.getFileid())) {
                JSONObject jsonObject = JSONObject.parseObject(response.getBody().toString());
                String jiraId = jsonObject.getString("id");
                String jiraKey = jsonObject.getString("key");
                String[] files = planConfirm.getFileid().split(",");
                for (int i = 0; i < files.length; i++) {
                    try {
                        CloseableHttpResponse responseFile = httpKitPostByFile(jiraKey, new File(uploadPath + "/" + files[i]));
                        log.info("同步JIRA添加方案附件-->" + jiraKey + "--->" + (uploadPath + "/" + files[i]) + "--->" + responseFile.getStatusLine());
                        log.info("同步JIRA添加方案附件-->" + jiraKey + "--->" + (uploadPath + "/" + files[i]) + "--->" + EntityUtils.toString(responseFile.getEntity()));
                    }
                    catch (FileNotFoundException e) {
                        e.printStackTrace();
                        log.info("同步JIRA添加方案附件-->" + jiraKey + "--->" + (uploadPath + "/" + files[i]), e);
                    }
                    catch (IOException e) {
                        e.printStackTrace();
                        log.info("同步JIRA添加方案附件-->" + jiraKey + "--->" + (uploadPath + "/" + files[i]), e);
                    }
                }
            }
            result.setSuccess(true);
        }
        else {
            result.setSuccess(false);
            result.setMessage("同步失败！");
        }
        result.setResult(JSONObject.parseObject(response.getBody().toString()));
        return result;
    }


    @ApiOperation(value = "JIRA-获取问题", notes = "JIRA-获取问题")
    @PostMapping(value = "/get/issue/{id}")
    public Result<JSONObject> getIssue(@PathVariable("id") String id) {
        Result<JSONObject> result = new Result<>();
        TtQuestionCollect questionCollect = ttQuestionCollectService.getById(id);
        HttpResponse<JsonNode> response = httpKitGetJson(questionCollect.getJiraid());
        log.info("JIRA-Code-->" + response.getStatus());
        log.info("JIRA-Content-->" + JSONObject.parseObject(response.getBody().toString()));
        if (200 == response.getStatus()) {
            log.info("JIRA-Update-->===================");
            ttQuestionCollectService.setStatusByJiraIdOrKey(id, response.getBody());
            result.setSuccess(true);
        }
        else {
            result.setSuccess(false);
            result.setMessage("操作失败！");
        }
        result.setResult(JSONObject.parseObject(response.getBody().toString()));
        return result;
    }

    private Object getRequestBody(TtQuestionCollect questionCollect, TtPlanConfirm planConfirm) {
        JsonNodeFactory factory = JsonNodeFactory.instance;
        ObjectNode bodyNode = factory.objectNode();
        {
            ObjectNode update = bodyNode.putObject("update");
            ObjectNode fields = bodyNode.putObject("fields");
            {
                // 概要
                fields.put("summary", questionCollect.getTitlesummary());
                // 描述
                fields.put("description", getDescription(questionCollect, planConfirm));
                // 所属项目
                ObjectNode project = fields.putObject("project");
                {
                    project.put("key", questionCollect.getProname());
                }
                // 问题类型
                ObjectNode issuetype = fields.putObject("issuetype");
                {
                    issuetype.put("name", oConvertUtils.isEmpty(questionCollect.getNeedtype()) ? "任务" : questionCollect.getNeedtype());
                }
                if(!"ZHKJ".equals(questionCollect.getProname())){
                    // 自定义字段，复杂度，默认为1.0
                    fields.put("customfield_10107", 1.0);
                }


                // 所属模块
                ArrayNode components = fields.putArray("components");
                if (oConvertUtils.isNotEmpty(questionCollect.getProject()) && !"无".equals(questionCollect.getProject())) {
                    List<String> componentList = Arrays.asList(questionCollect.getProject().split(","));
                    if (null != componentList) {
                        for (String component : componentList) {
                            ObjectNode components0 = components.addObject();
                            {
                                //components0.put("id", "10200");
                                components0.put("name", component);
                            }
                        }
                    }
                }

                // 优先级
                ObjectNode priority = fields.putObject("priority");
                {
                    priority.put("name", questionCollect.getPriority());
                }
                // 经办人
                if (oConvertUtils.isNotEmpty(questionCollect.getAssignee())) {
                    ObjectNode assignee = fields.putObject("assignee");
                    {
                        assignee.put("name", questionCollect.getAssignee());
                        assignee.put("active", true);
                    }
                }
                // sprint
                //ObjectNode customfield_10101 = fields.putObject("customfield_10101");
            }
        }
        return bodyNode;
    }

    private String getDescription(TtQuestionCollect questionCollect, TtPlanConfirm planConfirm) {
        String inFluEnCeRegion = "影响地区：" + (oConvertUtils.isNotEmpty(questionCollect.getInfluenceregion()) ? questionCollect.getInfluenceregion() : "无") + "\r\n\r\n";
        String inFluEnCeIndustry = "影响行业：" + (oConvertUtils.isNotEmpty(questionCollect.getInfluenceindustry()) ? getDictTextByCode(questionCollect.getInfluenceindustry()) : "无") + "\r\n\r\n";
        String questionContent = "详细内容：" + (oConvertUtils.isNotEmpty(deleteAllHTMLTag(questionCollect.getQuestioncontent())) ? deleteAllHTMLTag(questionCollect.getQuestioncontent()) : "无");

        String plan = "";
        if (null != planConfirm) {
            String planTitle = "方案简介：" + (oConvertUtils.isNotEmpty(planConfirm.getPlanname()) ? planConfirm.getPlanname() : "无") + "\r\n\r\n";
            String planContent = "方案详情：" + (oConvertUtils.isNotEmpty(deleteAllHTMLTag(planConfirm.getPlanDescribe())) ? deleteAllHTMLTag(planConfirm.getPlanDescribe()) : "无") + "\r\n\r\n";
            String planFiles = "方案附件：" + (oConvertUtils.isNotEmpty(planConfirm.getFileid()) ? "详见附件" : "无");
            plan = planTitle + planContent + planFiles;
        }

        return inFluEnCeRegion + inFluEnCeIndustry + questionContent + "\r\n\r\n" + plan;
    }

    private String getDictTextByCode(String inFluEnCeIndustry) {
        String[] hys = inFluEnCeIndustry.split(",");
        String result = "";
        for (int i = 0; i < hys.length; i++) {
            String text = sysDictItemMapper.queryTextByCode(hys[i]);
            result += text + ",";
        }
        return result.endsWith(",") ? result.substring(0, result.length() - 1) : result;
    }

    private static String deleteAllHTMLTag(String source) {

        if (source == null) {
            return "";
        }

        String s = source;
        /** 删除普通标签  */
        s = s.replaceAll("<(S*?)[^>]*>.*?|<.*? />", "");
        /** 删除转义字符 */
        s = s.replaceAll("&.{2,6}?;", "");
        return s;
    }

    private static HttpResponse<JsonNode> httpKitPostJson(Object requestBody) {
        Unirest.config().setObjectMapper(
                new ObjectMapper() {
                    private com.fasterxml.jackson.databind.ObjectMapper jacksonObjectMapper = new com.fasterxml.jackson.databind.ObjectMapper();

                    @Override
                    public <T> T readValue(String value, Class<T> valueType) {
                        try {
                            return jacksonObjectMapper.readValue(value, valueType);
                        }
                        catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    }

                    @Override
                    public String writeValue(Object value) {
                        try {
                            return jacksonObjectMapper.writeValueAsString(value);
                        }
                        catch (JsonProcessingException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
        );
        HttpResponse<JsonNode> response = Unirest.post(CREATE_ISSUE_URL)
                                                 .basicAuth(USERNAME, PASSWORD)
                                                 .header("Accept", "application/json")
                                                 .header("Content-Type", "application/json")
                                                 .body(requestBody)
                                                 .asJson();
        return response;
    }


    private static HttpResponse<JsonNode> httpKitGetJson(String idOrKey) {
        HttpResponse<JsonNode> response = Unirest.get(GET_ISSUE_URL + idOrKey)
                                                 .basicAuth(USERNAME, PASSWORD)
                                                 .header("Accept", "application/json")
                                                 .asJson();
        return response;
    }

    /**
     * 暂时不能用
     *
     * @param idOrKey
     * @param file
     * @return
     * @throws FileNotFoundException
     */
    private static HttpResponse<JsonNode> httpKitPostFile(String idOrKey, File file) throws FileNotFoundException {
        InputStream fileInputStream = new FileInputStream(file);
        log.info("" + ADD_ISSUE_ATTACHMENTS.replace("{issueIdOrKey}", idOrKey));
        HttpResponse response = Unirest.post(ADD_ISSUE_ATTACHMENTS.replace("{issueIdOrKey}", idOrKey))
                                       .basicAuth(USERNAME, PASSWORD)
                                       .header("Content-Type", "application/octet-stream")
                                       .field("file", fileInputStream, file.getName())
                                       .asString();
        return response;
    }

    private static CloseableHttpResponse httpKitPostByFile(String idOrKey, File file) throws FileNotFoundException {
        log.info("" + ADD_ISSUE_ATTACHMENTS.replace("{issueIdOrKey}", idOrKey));
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost post = new HttpPost(ADD_ISSUE_ATTACHMENTS.replace("{issueIdOrKey}", idOrKey));
        post.setHeader("Authorization", basicAuthHeader(USERNAME, PASSWORD));
        post.setHeader("X-Atlassian-Token", "nocheck");
        HttpEntity reqEntity = MultipartEntityBuilder.create()
                                                     .setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
                                                     .addBinaryBody("file",
                                                             new FileInputStream(file),
                                                             ContentType.APPLICATION_OCTET_STREAM,
                                                             file.getName())
                                                     .build();
        post.setEntity(reqEntity);
        post.setHeader(reqEntity.getContentType());
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(post);
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        return response;
    }

    public static String basicAuthHeader(String user, String pass) {
        if (user == null || pass == null) return null;
        try {
            byte[] bytes = (user + ":" + pass).getBytes("UTF-8");
            String base64 = DatatypeConverter.printBase64Binary(bytes);
            return "Basic " + base64;
        }
        catch (IOException ioe) {
            throw new RuntimeException("Stop the world, Java broken: " + ioe, ioe);
        }
    }

}
